package com.apes.scm.settle.settle.model;

import com.alibaba.fastjson.annotation.JSONField;
import com.apes.framework.jpa.BaseModel;
import com.apes.framework.jpa.DefaultPersistListener;
import com.apes.framework.jpa.comment.Comment;
import com.apes.framework.jpa.generator.ApesGenerator;
import com.apes.framework.util.ApesConst;
import com.apes.framework.util.DateUtil;
import com.apes.scm.account.tax.model.Tax;
import com.apes.scm.invoice.model.InvoiceItem;
import com.apes.scm.masterdata.frame.model.Dept;
import com.apes.scm.masterdata.product.model.Product;
import com.apes.scm.masterdata.product.model.ProductUom;
import com.apes.scm.masterdata.product.model.ServeType;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import org.hibernate.annotations.SelectBeforeUpdate;

import javax.persistence.*;
import javax.validation.constraints.NotNull;
import java.util.Date;
import java.util.Map;
import java.util.Objects;

@Getter
@Setter
@SelectBeforeUpdate
@DynamicInsert
@DynamicUpdate
@Entity
@EntityListeners(DefaultPersistListener.class)
@Table(name = SettleItem.CONST_TABLE_NAME,indexes = {
        @Index(name = "idx_settle_id", columnList = "settle_id")
})
public class SettleItem extends BaseModel {
    public static final String CONST_TABLE_NAME = "acc_settle_item";
    @Id
    @Column(name = "id")
    @ApesGenerator(code = CONST_TABLE_NAME, name = "结算商品")
    @Comment("结算单明细号")
    private String id;

    @NotNull
    @ManyToOne(optional = false)
    @JoinColumn(name = "settle_id", referencedColumnName = "id")
    @Comment("结算单号")
    private Settle settle;

//    @NotNull
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "product_uom_id", referencedColumnName = "id")
    @Comment("计量单位")
    private ProductUom uom;

    @Column(name = "price_unit", nullable = false, columnDefinition = ApesConst.FIELD_16_4)
    @Comment("单价")
    private double priceUnit = 0;

    @NotNull
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "tax_id", referencedColumnName = "id")
    @Comment("税率编码")
    private Tax tax;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="product_id", referencedColumnName="id", nullable = false)
    @Comment("商品编码")
    private Product product;

    @Column(name = "invoice_qty", nullable = false, columnDefinition = ApesConst.FIELD_16_4_0)
    @Comment("单据数量")
    private double invoiceQty = 0;

    @Column(name = "pending_qty", nullable = false, columnDefinition = ApesConst.FIELD_16_4_0)
    @Comment("待结算数量")
    private double pendingQty = 0;

    @Column(name = "actual_qty", nullable = false, columnDefinition = ApesConst.FIELD_16_4_0)
    @Comment("结算数量")
    private double actualQty = 0;

    public double getActualQty() {
        if(Math.abs(actualQty + pendingQty) != Math.abs(actualQty) + Math.abs(pendingQty)) throw new RuntimeException("结算数量有误！");
        if (Math.abs(actualQty) > Math.abs(pendingQty)) {
            throw new RuntimeException("结算数量不允许大于待结算数量！");
        }
        return actualQty;
    }

    @Column(name = "amt_untaxed", nullable = false, columnDefinition = ApesConst.FIELD_16_4)
    @Comment("无税金额")
    private double amtUntaxed = 0;

    @Column(name = "amt_tax", nullable = false, columnDefinition = ApesConst.FIELD_16_4)
    @Comment("税金")
    private double amtTax = 0;

    /*
    * 税金、无税金额 已减折扣项
    * */
    public void computeAmt() {
        Map result = this.getTax().computeAll(this.settle.getCompany(),this.priceUnit,this.actualQty);
        amtTax = ((Double) result.get("taxAmt")).doubleValue();
        amtUntaxed = ((Double) result.get("totalExcluded")).doubleValue();
        amount = ((Double) result.get("totalIncluded")).doubleValue();
        this.computeSettleAmt();
    }

    /*
    * 计算主表结算金额、返利金额、结算税金、销售/入库金额等
    * */
    private void computeSettleAmt() {
        if ("PurchaseReturn".equals(originBusinessType) || "SaleReturn".equals(originBusinessType)|| "Redemption".equals(originBusinessType)) {
            settle.changeReturnAmount(amount);
        } else if ("PriceChange".equals(originBusinessType)) {
            settle.changeChangeAmount(amount);
        }
        settle.changeInboundAmount(amount);

        if("Supplier".equals(settle.getPartner().getRole().getId())){
            settle.changeSettleAmount(amount);
            settle.changeRebateAmount(0);
        }else{
            settle.changeSettleAmount(amount-discount);
            settle.changeRebateAmount(discount);
        }
        settle.changeSettleTax(amtTax);
        settle.changeInboundTax(amtTax);
    }

    @Column(name = "amount", nullable = false, columnDefinition = ApesConst.FIELD_16_4)
    @Comment("结算金额")
    private double amount = 0;

    @Column(name = "discount", nullable = false, columnDefinition = ApesConst.FIELD_16_4_0)
    @Comment("折扣/返利")
    private double discount = 0;

    @NotNull
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "invoice_id", referencedColumnName = "id")
    @Comment("账单明细编码")
    private InvoiceItem invoiceItem;

    /*
    * 冗余字段保存,方便查询
    * */

    @Column(name = "origin_business_type", length = 32, nullable = true)
    @Comment("源单类型")
    private String originBusinessType;

    @Column(name = "origin", length = 30, nullable = true)
    @Comment("源单号")
    private String origin;

    @Column(name = "origin_item_id", length = 30)
    @Comment("源单明细行号")
    private String originItemId;

    @JSONField(format = DateUtil.SHOW_DATE_FORMAT)
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "occurrence_date")
    @Comment("发生日期")
    private Date occurrenceDate;

    @Column(name = "car_license", length = 64)
    @Comment("车牌号码")
    private String carLicense;

    @Transient
    private Dept dept;

    public Dept getDept() {
        if(Objects.isNull(invoiceItem)) return this.dept;
        return invoiceItem.getInvoice() != null ? invoiceItem.getInvoice().getDept() : null;
    }

    @Column(name = "invoiced_amount", columnDefinition = ApesConst.FIELD_MONEY_16_4_0)
    @Comment("已开票金额")
    private double invoicedAmount = 0;

    @Column(name = "invoice_number", length = 256)
    @Comment("发票号码")
    private String invoiceNumber;

    @Column(name = "supplier_ref", length = 30)
    @Comment("第三方单号")
    private String supplierRef;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "serve_type_id", referencedColumnName = "id")
    @Comment("服务类型编码")
    private ServeType serveTypeId;

    @Column(name = "source", length = 32)
    @Comment("来源单号")
    private String source;

    @Column(name = "source_business_type", length = 32)
    @Comment("来源单据类型")
    private String sourceBusinessType;

    @Column(name = "floor_price", nullable = false, columnDefinition = ApesConst.FIELD_16_4_0)
    @Comment("供应商低价")
    private double floorPrice;

    @Column(name = "note", length = 1000)
    @Comment("备注")
    private String note; //备注
}
